#include "addresswidget.h"
#include "adddialog.h"

#include <QtWidgets>

//! [0]
AddressWidget::AddressWidget(QWidget *parent)
    : QTabWidget(parent),
      table(new TableModel(this)),
      newAddressTab(new NewAddressTab(this))
{
    connect(newAddressTab, &NewAddressTab::sendDetails,
        this, &AddressWidget::addEntry);

    addTab(newAddressTab, tr("Address Book"));

    setupTabs();
}
//! [0]

//! [2]
void AddressWidget::showAddEntryDialog()
{
    AddDialog aDialog;

    if (aDialog.exec())
        addEntry(aDialog.domain(), aDialog.username(), aDialog.password(), aDialog.note());
}
//! [2]

//! [3]
void AddressWidget::addEntry(const QString &domain, const QString &username,
                             const QString &password, const QString &note)
{
    if (!table->getContacts().contains({ domain, username, password, note })) {
        table->insertRows(0, 1, QModelIndex());

        QModelIndex index = table->index(0, 0, QModelIndex());
        table->setData(index, domain, Qt::EditRole);
        index = table->index(0, 1, QModelIndex());
        table->setData(index, username, Qt::EditRole);
        index = table->index(0, 2, QModelIndex());
        table->setData(index, password, Qt::EditRole);
        index = table->index(0, 3, QModelIndex());
        table->setData(index, note, Qt::EditRole);
        removeTab(indexOf(newAddressTab));
    } else {
        QMessageBox::information(this, tr("Duplicate Domain"),
            tr("The domain \"%1\" already exists.").arg(domain));
    }
}
//! [3]

//! [4a]
void AddressWidget::editEntry()
{
    QTableView *temp = static_cast<QTableView*>(currentWidget());
    QSortFilterProxyModel *proxy = static_cast<QSortFilterProxyModel*>(temp->model());
    QItemSelectionModel *selectionModel = temp->selectionModel();

    const QModelIndexList indexes = selectionModel->selectedRows();
    QString domain;
    QString username;
    QString password;
    QString note;
    int row = -1;

    for (const QModelIndex &index : indexes) {
        row = proxy->mapToSource(index).row();
        QModelIndex domainIndex = table->index(row, 0, QModelIndex());
        QVariant varDomain = table->data(domainIndex, Qt::DisplayRole);
        domain = varDomain.toString();

        QModelIndex usernameIndex = table->index(row, 1, QModelIndex());
        QVariant varUsername = table->data(usernameIndex, Qt::DisplayRole);
        username = varUsername.toString();

        QModelIndex passwordIndex = table->index(row, 2, QModelIndex());
        QVariant varPassword = table->data(passwordIndex, Qt::DisplayRole);
        password = varPassword.toString();

        QModelIndex noteIndex = table->index(row, 3, QModelIndex());
        QVariant varNote = table->data(noteIndex, Qt::DisplayRole);
        note = varNote.toString();
    }
//! [4a]

//! [4b]
    AddDialog aDialog;
    aDialog.setWindowTitle(tr("Edit a Contact"));
    aDialog.editAddress(domain, username, password, note);

    if (aDialog.exec()) {
        const QString newUsername = aDialog.username();
        if (newUsername != username) {
            const QModelIndex index = table->index(row, 1, QModelIndex());
            table->setData(index, newUsername, Qt::EditRole);
        }
        const QString newPassword = aDialog.password();
        if (newPassword != password) {
            const QModelIndex index = table->index(row, 2, QModelIndex());
            table->setData(index, newPassword, Qt::EditRole);
        }
        const QString newNote = aDialog.note();
        if (newNote != note) {
            const QModelIndex index = table->index(row, 3, QModelIndex());
            table->setData(index, newNote, Qt::EditRole);
        }
    }
}
//! [4b]

//! [5]
void AddressWidget::removeEntry()
{
    QTableView *temp = static_cast<QTableView*>(currentWidget());
    QSortFilterProxyModel *proxy = static_cast<QSortFilterProxyModel*>(temp->model());
    QItemSelectionModel *selectionModel = temp->selectionModel();

    const QModelIndexList indexes = selectionModel->selectedRows();

    for (QModelIndex index : indexes) {
        int row = proxy->mapToSource(index).row();
        table->removeRows(row, 1, QModelIndex());
    }

    if (table->rowCount(QModelIndex()) == 0)
        insertTab(0, newAddressTab, tr("Address Book"));
}
//! [5]

//! [1]
void AddressWidget::setupTabs()
{
    const auto groups = { "ABC", "DEF", "GHI", "JKL", "MNO", "PQR", "STU", "VW", "XYZ" };

    for (const QString &str : groups) {
        const auto regExp = QRegularExpression(QString("^[%1].*").arg(str),
                                               QRegularExpression::CaseInsensitiveOption);

        auto proxyModel = new QSortFilterProxyModel(this);
        proxyModel->setSourceModel(table);
        proxyModel->setFilterRegularExpression(regExp);
        proxyModel->setFilterKeyColumn(0);

        QTableView *tableView = new QTableView;
        tableView->setModel(proxyModel);
        tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
        tableView->horizontalHeader()->setStretchLastSection(true);
        tableView->verticalHeader()->hide();
        tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
        tableView->setSelectionMode(QAbstractItemView::SingleSelection);
        tableView->setSortingEnabled(true);

        connect(tableView->selectionModel(), &QItemSelectionModel::selectionChanged,
                this, &AddressWidget::selectionChanged);

        connect(this, &QTabWidget::currentChanged, this, [this, tableView](int tabIndex) {
            if (widget(tabIndex) == tableView)
                emit selectionChanged(tableView->selectionModel()->selection());
        });

        addTab(tableView, str);
    }
}
//! [1]

//! [7]
void AddressWidget::readFromFile(const QString &fileName)
{
    QFile file(fileName);

    if (!file.open(QIODevice::ReadOnly)) {
        QMessageBox::information(this, tr("Unable to open file"),
            file.errorString());
        return;
    }

    QVector<Contact> contacts;
    QDataStream in(&file);
    in >> contacts;

    if (contacts.isEmpty()) {
        QMessageBox::information(this, tr("No contacts in file"),
                                 tr("The file you are attempting to open contains no contacts."));
    } else {
        for (const auto &contact: qAsConst(contacts))
            addEntry(contact.domain, contact.username, contact.password, contact.note);
    }
}
//! [7]

//! [6]
void AddressWidget::writeToFile(const QString &fileName)
{
    QFile file(fileName);

    if (!file.open(QIODevice::WriteOnly)) {
        QMessageBox::information(this, tr("Unable to open file"), file.errorString());
        return;
    }

    QDataStream out(&file);
    out << table->getContacts();
}
//! [6]
